using System;
using System.Collections.Generic;
using System.Text;

using Yorrick.FlickrMetadataSynchr.Data;

namespace Yorrick.FlickrMetadataSynchr.Match
{
    /// <summary>
    /// Factory class that constructs instances that implement <see cref="IMetadataMatcher"/>.
    /// </summary>
    internal static class MetadataMatcherFactory
    {
        #region Public methods
        /// <summary>
        /// Returns a <see cref="IMetadataMatcher"/> instance that implements the requested 
        /// <see cref="MatchBehavior"/>.
        /// </summary>
        /// <param name="matchBehavior">The desired match behavior.</param>
        /// <returns>A <see cref="IMetadataMatcher"/> instance that implements the requested 
        /// <see cref="MatchBehavior"/>.</returns>
        public static IMetadataMatcher GetMetadataMatcher(MatchBehavior matchBehavior)
        {
            switch (matchBehavior)
            {
                case MatchBehavior.DateTaken:
                    return GetDateTakenMatcher();

                case MatchBehavior.FileName:
                    return GetFileNameMatcher();

                case MatchBehavior.SmartMatch:
                    List<IMetadataMatcher> metadataMatchers = new List<IMetadataMatcher>(4);

                    metadataMatchers.Add(GetFlickrIdMatcher());
                    metadataMatchers.Add(GetDateTakenAndTitleMatcher());
                    metadataMatchers.Add(GetDateTakenMatcher());
                    metadataMatchers.Add(GetFileNameMatcher());

                    return new MultiPassMetadataMatcher(metadataMatchers);

                default:
                    throw new ArgumentOutOfRangeException("matchBehavior", matchBehavior, "Unsupported match behavior.");
            }
        }
        #endregion

        #region Private methods
        /// <summary>
        /// Returns an <see cref="IMetadataMatcher"/> instance that matches on date taken.
        /// </summary>
        /// <returns>An <see cref="IMetadataMatcher"/> instance that matches on date taken.</returns>
        private static IMetadataMatcher GetDateTakenMatcher()
        {
            return new MetadataSingleValueMatcher<DateTime>(
                "date taken", 
                MetadataDelegates.GetDateTaken, 
                MetadataDelegates.GetDateTaken,
                MetadataDelegates.IsNullMatchKey);
        }

        /// <summary>
        /// Returns an <see cref="IMetadataMatcher"/> instance that matches on combination of date taken and title/filename.
        /// </summary>
        /// <returns>An <see cref="IMetadataMatcher"/> instance that matches on date taken.</returns>
        private static IMetadataMatcher GetDateTakenAndTitleMatcher()
        {
            return new MetadataSingleValueMatcher<DateTakenTitleMatchKey>(
                "date taken and title/filename", 
                MetadataDelegates.GetLocalDateTakenTitleMatchKey, 
                MetadataDelegates.GetFlickrDateTakenTitleMatchKey,
                MetadataDelegates.IsNullMatchKey);
        }

        /// <summary>
        /// Returns an <see cref="IMetadataMatcher"/> instance that matches on title/file name.
        /// </summary>
        /// <returns>An <see cref="IMetadataMatcher"/> instance that matches on title/file name.</returns>
        private static IMetadataMatcher GetFileNameMatcher()
        {
            return new MetadataSingleValueMatcher<string>(
                "title/filename", 
                MetadataDelegates.GetFileNameWithoutExtension, 
                MetadataDelegates.GetTitle,
                MetadataDelegates.IsNullMatchKey);
        }

        /// <summary>
        /// Returns an <see cref="IMetadataMatcher"/> instance that matches on Flickr id.
        /// </summary>
        /// <returns>An <see cref="IMetadataMatcher"/> instance that matches on Flickr id.</returns>
        private static IMetadataMatcher GetFlickrIdMatcher()
        {
            return new MetadataSingleValueMatcher<string>(
                "Flickr id", 
                MetadataDelegates.GetFlickrId, 
                MetadataDelegates.GetFlickrId,
                MetadataDelegates.IsNullMatchKey);
        }
        #endregion
    }
}
